﻿using System;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Configuration;
using System.IO;
using System.Timers;
using System.Reflection;
using PharmClientService.ServParsSite;
using System.ServiceModel;
using System.Web;
using System.Text;

namespace PharmClientService
{
    public partial class PharmClientService : ServiceBase
    {
        private int trynumber = 1;
        private int check_instal = 1;
        private ServParsSiteClient client;
        private int clientid = 0;
        private Timer aTimer;
        private string curdir = "";

        public PharmClientService()
        {
            InitializeComponent();
            if (!EventLog.SourceExists("PharmClientServiceSource"))
            {
                EventLog.CreateEventSource("PharmClientServiceSource", "PharmClientServiceLog");
            }
            eventLog1.Source = "PharmClientServiceSource";
            eventLog1.Log = "PharmClientServiceLog";
            eventLog1.MaximumKilobytes = 1024;
            eventLog1.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 5);
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                client = new ServParsSiteClient();
                //client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
                string log = "Запуск службы";
                bool error = false;
                try
                {
                    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    clientid = Convert.ToInt32(config.AppSettings.Settings["clientid"].Value);
                    log += "\nTекущее значение clientid = " + clientid;
                    curdir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    string ip = (new WorkPlace()).GetIP();
                    log += "\n\nОпределение кода аптеки";
                    int pharmCode = (new WorkPlace()).GetPharmCode();
                    
                    //client.ClientPharmCodeUpd(clientid, pharmCode);
                    //config.AppSettings.Settings.Add("pharmcode", pharmCode.ToString());
                    //config.Save(ConfigurationSaveMode.Modified);
                    //ConfigurationManager.RefreshSection("appSettings");

                    if (clientid == 0)
                    {
                        string comment = Environment.MachineName;
                        string windowsInfo = (new WorkPlace()).GetOSName("");
                        log += "\n Получение списка и версий exe-файлов";
                        string[] filelist = Directory.GetFiles(curdir, "*.exe");
                        
                        DataTable files = new DataTable("files");
                        files.Columns.Add("fileid");
                        files.Columns.Add("filename");
                        files.Columns.Add("fileversion");
                        foreach (string s in filelist)
                        {
                            object[] row = new object[3] { null, Path.GetFileName(s), FileVersionInfo.GetVersionInfo(s).FileVersion };
                            files.Rows.Add(row);
                        }

                        clientid = client.NewClient(ip, comment, files, pharmCode, windowsInfo);
                        log += "\n\nЗапись в config значений:\nclientid = " + clientid + "\nip = " + ip + "\ncomment = " + comment;
                        config.AppSettings.Settings["clientid"].Value = clientid.ToString();
                        config.AppSettings.Settings["ip"].Value = ip;
                        config.AppSettings.Settings["comment"].Value = comment;
                        config.AppSettings.Settings["pharmcode"].Value = pharmCode.ToString();
                        config.Save(ConfigurationSaveMode.Modified);
                        ConfigurationManager.RefreshSection("appSettings");
                        log += "\nЗначения сохранены";
                    }
                    else
                    {
                        if(ip != "")
                            if (config.AppSettings.Settings["ip"].Value != ip)
                            {
                                log += "\n\nИзменение старого IP:\nстарый IP = " + config.AppSettings.Settings["ip"].Value + "\nновый IP = " + ip;
                                client.ClientIPUpd(clientid, ip);
                                config.AppSettings.Settings["ip"].Value = ip;
                                config.Save(ConfigurationSaveMode.Modified);
                                ConfigurationManager.RefreshSection("appSettings");
                                log += "\nIP изменен";
                            }
                        if (config.AppSettings.Settings["pharmcode"].Value != pharmCode.ToString() && pharmCode > 0)
                        {
                            log += "\n\nИзменение кода аптеки:\nстарый = " + config.AppSettings.Settings["pharmcode"].Value + "\nновый = " + pharmCode.ToString();
                            client.ClientPharmCodeUpd(clientid, pharmCode);
                            config.AppSettings.Settings["pharmcode"].Value = pharmCode.ToString();
                            config.Save(ConfigurationSaveMode.Modified);
                            ConfigurationManager.RefreshSection("appSettings");
                            log += "\nКод изменен";
                        }
                        //client.ClientWinInfoUpd(clientid, windowsInfo);
                    }
                }
                catch (Exception ex)
                {
                    log += "\n" + ex.Data.ToString() + "\t" + ex.Message;
                    error = true;
                }
                finally
                {
                    log += "\n\nЗапуск таймера для парсинга";
                    aTimer = new System.Timers.Timer(60000);
                    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
                    aTimer.Enabled = true;
                    if (aTimer.Enabled) log += "\nТаймер активен";
                    else log += "\nТаймер не активен";
                    client.Close();
                    if (error) eventLog1.WriteEntry(log,EventLogEntryType.Error);
                    else eventLog1.WriteEntry(log);
                }
            }
            catch (Exception ex)
            {
                eventLog1.WriteEntry(ex.Data.ToString() + "\n" + ex.Message, EventLogEntryType.Error);
            }
            finally
            {
                if (client.State == CommunicationState.Opened)
                    client.Close();
            }
    
        }

        protected override void OnStop()
        {
            if (client.State == CommunicationState.Opened) client.Close();
            eventLog1.WriteEntry("Остановка службы");
        }
        
        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            ParsSite();
            SearchUpdate();
        }

        private void ParsSite()
        {
            string log = trynumber.ToString() + "\n" + DateTime.Now.ToString("HH-mm-ss dd-MM-yyyy");
            EventLogEntryType elet = EventLogEntryType.Information;
            bool exc = false;
            bool fl_b = false;
            //client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
            try
            {
                client = new ServParsSiteClient();
                WorkPlanStr wps = new WorkPlanStr();
                try
                {
                    wps = (WorkPlanStr)client.IAmFree(clientid);
                    if (wps.WebSiteID > 0)
                    {
                        log += "\nDrug = " + wps.Drug + "; UrlPath = " + wps.UrlPath + "; UrlParam = " + wps.UrlParam + "; WorkPlanStrID = " + wps.WorkPlanStrID + "; WebSiteID = " + wps.WebSiteID;
                        ParsingSites ps = new ParsingSites();
                        DataTable CompPrice = ps.SitePars(wps.UrlPath, wps.UrlParam.Replace("***", System.Uri.EscapeDataString(wps.Drug)), wps.WebSiteID, wps.Drug, "");
                        //{
                        log += "\n" + wps.UrlParam.Replace("***", System.Uri.EscapeDataString(wps.Drug));
                        log += "\n" + wps.UrlPath + ' ' + wps.UrlParam.Replace("***", System.Uri.EscapeDataString(wps.Drug)) + ' ' + wps.Drug;
                        //}
                        log += "\nКоличество строк: " + CompPrice.Rows.Count.ToString();
                        CompPrice.TableName = "CompPrice";
                        CompPrice.Columns.Add("parentid");
                        client.CompPriceIns(CompPrice, wps.WorkPlanStrID, clientid);
                        fl_b = true;
                    }
                    else
                    {
                        if (wps.WebSiteID == -1)
                        {
                            log += "\nЭтот клиент не должен работать.\nПараметр Closed = 1, таблица Client.\nТаймер службы будет остановлен.";
                            aTimer.Stop();
                        }
                    }
                }
                catch (Exception ex)
                {
                    log += "\n" + ex.Message;
                    log += "\nОШИБКА";
                    exc = true;
                }
                if (fl_b && wps.WebSiteID > 0) log += "\nУСПЕХ";

                if (wps.WebSiteID != 0 || exc)
                {
                    log += "\n" + DateTime.Now.ToString("HH-mm-ss dd-MM-yyyy");
                }
            }
            catch (Exception ex)
            {
                log += "\n" + ex.Data.ToString() + "\n" + ex.Message;
                elet = EventLogEntryType.Error;  
            }
            finally
            {
                if (client.State == CommunicationState.Opened)
                    client.Close();
                trynumber++;
                if (elet == EventLogEntryType.Error || exc || fl_b) eventLog1.WriteEntry(log, elet, 1);
            }
        }

        private void SearchUpdate()
        {
            string log = "";
            EventLogEntryType elet = EventLogEntryType.Information;
            if (check_instal >= 5)
            {
                client = new ServParsSiteClient();
                try
                {
                    string ip = (new WorkPlace()).GetIP();
                    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    if (ip != "")
                        if (config.AppSettings.Settings["ip"].Value != ip)
                        {
                            log += "\nИзменение старого IP:\nстарый IP = " + config.AppSettings.Settings["ip"].Value + "\nновый IP = " + ip;
                            client.ClientIPUpd(clientid, ip);
                            config.AppSettings.Settings["ip"].Value = ip;
                            config.Save(ConfigurationSaveMode.Modified);
                            ConfigurationManager.RefreshSection("appSettings");
                            log += "\nIP изменен";
                        }

                    FileNameVersion fnv = (FileNameVersion)client.GetInstallerInfo();
                    if (fnv.FileName != "")
                    {
                        log += "\nПроверка обновлений";
                        string currfile = curdir + @"\" + fnv.FileName;
                        string currvers = FileVersionInfo.GetVersionInfo(currfile).FileVersion;
                        if (currvers != fnv.FileVersion)
                        {
                            log += "\nЗагрузка нового установщика";
                            var chukscount = client.GetFileChunksCount(fnv.FileName);
                            var stream = File.Create(currfile);
                            for (var i = 0; i < chukscount; i++)
                            {
                                var chunk = client.GetFileChunk(fnv.FileName, i);
                                var chunkBytes = Convert.FromBase64String(chunk);
                                stream.Write(chunkBytes, 0, chunkBytes.Length);
                            }
                            stream.Close();
                            log += "\nУстановщик загружен";
                            client.ClientFileVersionUpd(clientid, fnv.FileName, FileVersionInfo.GetVersionInfo(currfile).FileVersion);
                            //log += "\nОстановка таймера";
                            //aTimer.Stop();
                            log += "\nЗапуск установщика";
                            Process.Start(currfile, "-upd -" + clientid.ToString());
                        }
                        else
                        {
                            FileNameVersion currentservice = (FileNameVersion)client.GetWinServiceInfo();
                            string currservice = curdir + @"\" + currentservice.FileName;
                            string currservicevers = FileVersionInfo.GetVersionInfo(currservice).FileVersion;
                            if (currentservice.FileVersion != currservicevers)
                            {
                                log += "\nНайдена новая версия службы";
                                //log += "\nОстановка таймера";
                                //aTimer.Stop();
                                log += "\nЗапуск инсталятора";
                                Process.Start(currfile, "-upd -" + clientid.ToString());
                            }
                        }
                    }
                }
                catch (Exception excep)
                {
                    log += "\n" + excep.Data.ToString() + "\t" + excep.Message;
                    elet = EventLogEntryType.Error;
                }
                finally
                {
                    if (client.State == CommunicationState.Opened)
                        client.Close();
                    check_instal = 1;
                    eventLog1.WriteEntry(log, elet, 2);
                }
            }
            else check_instal++;
        }
    }
}
